#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/completion.h>
#include <linux/types.h>

struct spi_vir_driver_data {
    struct spi_bitbang bitbang; /* bitbang has to be first */
    struct spi_master *master;
    struct platform_device *pdev;
    struct completion xfer_done;
    bool slave_mode;
    bool slave_aborted;
};

static int spi_vir_slave_abort(struct spi_master *master)
{
    struct spi_vir_driver_data *svdd = spi_master_get_devdata(master);

	svdd->slave_aborted = true;
	complete(&svdd->xfer_done);

	return 0;
}

static int spi_vir_slave_transfer(struct spi_device *spi, struct spi_transfer *transfer)
{   
    struct spi_vir_driver_data *svdd = spi_master_get_devdata(spi->master);
    int ret = transfer->len;

    if (svdd->slave_mode) {
        /* 重新初始化事件 */
        reinit_completion(&svdd->xfer_done);
        svdd->slave_aborted = false;

        /* 等待master硬件传输完成中断唤醒 */
        // complete(&svdd->xfer_done);

        /* 等待事件唤醒*/
        if (wait_for_completion_interruptible(&svdd->xfer_done) || svdd->slave_mode) {
            dev_dbg(&spi->dev, "interrupted\n");
		    ret = -EINTR;
        }
    }

    return ret;
}

static void spi_vir_slave_chipselect(struct spi_device *spi, int is_active)
{
    
}


static int spi_vir_slave_probe(struct platform_device *pdev)
{
    bool slave_mode;
    struct spi_master *master = NULL;
    struct spi_vir_driver_data *svdd = NULL;
    int ret = 0;
    struct device_node *np = pdev->dev.of_node;

    slave_mode = of_property_read_bool(np, "spi-slave");
    if (slave_mode) {
        master = spi_alloc_slave(&pdev->dev, sizeof(struct spi_vir_driver_data));
        
    }

    if (!master) {
        dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
        return -ENOMEM;
    }

    /* 设置私有数据 */
    svdd = spi_master_get_devdata(master);
    platform_set_drvdata(pdev, svdd);
    svdd->master = master;
    svdd->pdev = pdev;
    svdd->slave_mode = slave_mode;

    /* 初始化completion */
    init_completion(&svdd->xfer_done);

    /* 设置bitbang  _master */
    svdd->bitbang.master = master;

    /* 设置txrx_bufs函数 */
    svdd->bitbang.txrx_bufs = spi_vir_slave_transfer;

    /* 设置chipselect函数 */
    svdd->bitbang.chipselect = spi_vir_slave_chipselect;

    /* 设置slave_abort函数退出 */
    svdd->bitbang.master->slave_abort = spi_vir_slave_abort;

    /* 设置master设备树 */
    master->dev.of_node = pdev->dev.of_node;

    /* 绑定spi_bitbang */
    ret = spi_bitbang_start(&svdd->bitbang);
	if (ret) {
		dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
		spi_master_put(master);
        return ret;
	}

    return 0;
    
}

static int spi_vir_slave_remove(struct platform_device *pdev)
{
    struct spi_vir_driver_data *svdd = platform_get_drvdata(pdev);
    spi_bitbang_stop(&svdd->bitbang);
    spi_master_put(svdd->master);
    
    return 0;
}

static const struct of_device_id spi_vir_slave[] = {
    { .compatible = "jz2440,virtual_spi_slave", },
    {},
};

static struct platform_driver spi_vir_slave_driver = {
    .probe = spi_vir_slave_probe,
    .remove = spi_vir_slave_remove,
    .driver = {
        .name = "jz-spi-vir-slave",
        .of_match_table = of_match_ptr(spi_vir_slave),
    }
};


static int spi_vir_slave_init(void)
{
    int ret = platform_driver_register(&spi_vir_slave_driver);
    if (ret < 0) {
        dev_err(NULL, "spi_vir_master_init failed");
        return -EBUSY;
    }

    return 0;
}

static void spi_vir_slave_exit(void)
{
    platform_driver_unregister(&spi_vir_slave_driver);
}

module_init(spi_vir_slave_init);
module_exit(spi_vir_slave_exit);

MODULE_AUTHOR("huang");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("spi master driver");


